<?php
// +------------------------------ Token相关 ----------------------------------------

namespace app\common\service;

class TokenService
{
    // token过期时间（秒）
    protected $expire = 7200; // 2小时
    
    // 密钥
    protected $secret = 'maohe101';
    
    /**
     * 生成token
     *
     * @param int $userId 用户ID
     * @return string
     */
    public function createToken($userId)
    {
        $time = time();
        $tokenData = [
            'iss' => 'thinkphp_server', // 签发者
            'iat' => $time,             // 签发时间
            'exp' => $time + $this->expire, // 过期时间
            'user_id' => $userId        // 用户ID
        ];
        
        return $this->encodeToken($tokenData);
    }
    
    /**
     * 验证token
     *
     * @param string $token
     * @return array|bool 成功返回用户数据，失败返回false
     */
    public function verifyToken($token)
    {
        // 去除可能的Bearer前缀
        $token = str_replace('Bearer ', '', $token);
        
        try {
            $tokenData = $this->decodeToken($token);
            
            // 验证是否过期
            if (time() > $tokenData['exp']) {
                return false;
            }
            
            return $tokenData;
        } catch (\Exception $e) {
            return false;
        }
    }
    
    /**
     * 编码token（简化版JWT）
     *
     * @param array $data
     * @return string
     */
    protected function encodeToken($data)
    {
        $header = base64_encode(json_encode(['alg' => 'HS256', 'typ' => 'JWT']));
        $payload = base64_encode(json_encode($data));
        $signature = hash_hmac('sha256', $header . '.' . $payload, $this->secret);
        
        return $header . '.' . $payload . '.' . $signature;
    }
    
    /**
     * 解码token
     *
     * @param string $token
     * @return array
     * @throws \Exception
     */
    protected function decodeToken($token)
    {
        $parts = explode('.', $token);
        
        if (count($parts) != 3) {
            throw new \Exception('Token格式错误');
        }
        
        list($header, $payload, $signature) = $parts;
        
        // 验证签名
        $checkSignature = hash_hmac('sha256', $header . '.' . $payload, $this->secret);
        
        if ($signature !== $checkSignature) {
            throw new \Exception('Token签名验证失败');
        }
        
        return json_decode(base64_decode($payload), true);
    }
}
